/*
 * ruletangle.h
 *
 *  Created on: Jan 17, 2012
 *      Author: Mo
 */

#pragma once

#include "rectangle2.h"
#include "iruleption.h"

/** This class STORES ONE RULE ONLY. It is similar to RuleTangle class, unless:
 *  1- All the long instances have the label = 1;
 *  2- only the long instances whose lable are 1 are stored. if a long instance
 *  is not stored or if a given long instance does not exist, its lable will be calculated az 0.
 *  3- The label is not stored (or is not used). It is assumed that all the labels are 1.
 */
class Ruletangle2 : public IRuleption
{
private:
	LongInstance majorLongInstance;			//!< The longinstance of the rule.
	//LongInstance minorLongInstance;		//!< We need this to calculate the minor Rectangle2s.
	//vector<Rectangle2> majorRectangle2;	//!< The set of Rectangle2s whose longinstance are the same. DO WE NEED THIS??
	vector<Rectangle2> minorRectangle2; 	//!< The set of Rectangle2s with different label than above

	/**
	 * Adds a coordinate to the set of minor Rectangle2s and updates both major and minor set of Rectangle2s.
	 * This function will automatically divide the major Rectangle2s if necessary, and create or expand a
	 * minor Rectangle2 to include the recently added coordinate.
	 */
	//void addMinorCoo (const Coordinate& coo); NOT NEEDED ANYMORE

	/**
	 * This function updates the vector of major Rectangle2s by dividing the single major Rectangle2 who surrounds the 
	 * given coordination. Nothing will be done if no major Rectangle2 surrounds the given coordination. The vector 
	 * of major Rectangle2s will be automatically updated. 
	 * \return the number of new Rectangle2s. -1 if error happens, 0 if no major Rectangle2 surrounds the coo, 2, 3 or 4
	 * if Rectangle2 needs to break down.
	 * NOTE: It is not very optimized now. It divides in 8 new Rectangle2s without merging those who can be merged.
	 * remember to merge them later.
	 */
	//int divideMajorsOn (const Coordinate& coo);

	/**
	 * This function creates and returns the smallest Rectangle2 that covers all the minor coordinates.
	 */
	Rectangle2 makeRectFromMinors();

	/** Returns true if there is no major coordinate in the given Rectangle2. */
	bool noMajorInside (const Rectangle2& Rectangle2);

	/** Returns true if there is no major coordinate in the given Rectangle. */
	bool noMajorInside (const Rectangle& Rectangle);

	/** Returns the number of major coordinates inside the given Rectangle2.*/
	int majorsInside (const Rectangle2& Rectangle2);

	/** Returns the number of major coordinates inside the given Rectangle2.*/
	int majorsInside (const Rectangle& Rectangle2, bool reportOnInside = false);

	/** Divides the source Rectangle2 into two Rectangle2s t1 and t2 in a way that the sum of major coordinates in t1 and t2 are minimized.*/
	//void divideMinErrors (const Rectangle& source, Rectangle& t1, Rectangle& t2);

	/**
	 * A helper function. Tells which Rectangle2 in minorRectangle2 needs the lowest expansion to swallow the given
	 * coordinate without getting a coo of the majorLI in it. Returns -1 if no such Rectangle2 exists.
	 * Note: I could drop the majorLI parameter and use 'this->majorLongInstance' instead, but there is no guarantee
	 * that 'this-majorLongInstance' include the vector of coo in the lifetime of this object. (They might get deleted 
	 * as we do not need them anymore after we have this Ruletangle2 object).
	 */
	 int minRectIndexWithMinExpansion (const LongInstance& majorLI, const Coordinate& toBeAdded) const;

	 /**
	  * This function inputs a Rectangle and a vector of Coordinates, outputs a vector of Rectangles who cover all the 
	  *inputRectangle::coos but whose union does not cover any of the given coos in the second parameter.
	  */
	 //vector<Rectangle> breakRectangleToExcludeCoos (const Rectangle& initRect, const vector<Coordinate>& coos) const;

public:
	Ruletangle2(void);
	Ruletangle2(const Ruletangle2& other);

	/**
	 * Constructor. Takes two long instances with all their coordinates and creates a ruletangle2 object. The "type" parameter tells how the 
	 * object should be created:
	 * type = 0: The major label is always white (0). The exceptions (the minor rectangles) indicate the location of black (1) pixels.
	 * type = 1: The major label is always black (1). The exceptions (the minor rectangles) indicate the location of white (0) pixels.
	 * type = 2: The major label is the one accordint to which there will be less minor rectangles.
	 * type = 3: The major label is l1's label
	 * type = 4: The major label is l2's label
	 * algorithm = 1: top-down heuristic method
	 * algorithm = 2: bottom-up heuristic method
	 * algorithm = 3: evolutionary algorithm
	 * \note: current implementation sets the major label to black (1).
	 */
	//TODO: add the different types.
	Ruletangle2(const LongInstance& l1, const LongInstance& l2, Rectangle2FormationAlgorithmType algorithmType = bottomup, int type = 1);	//!< NOTE: l1 and l2 are conflicting rules, with the same IF part and different lable
	Ruletangle2(const LongInstance& l); //!< C'tor with only one LongInstance parameter. Assumes there is no conflicting rule.
	~Ruletangle2();


	/** Returns true is the given coordination exists in one of the sub-Rectangle2s. */
	bool hasCoo (const Coordinate& coo);

	/** returns the label of the given coordination.
	 *  This functions finds the rule (i.e.)long instance that includes the given coordination
	 *  and returns the rule label (then-part) for it.
	 */
	int label (const vector<Neighborhood*>& nbr, const Coordinate& coo) const;

	/**
	 * Returns true if the given IF part (as a Neighborhood vector) is the same as the IF part in this Ruletangle2 object.
	 * i.e. if the rule of the ruletangle applies to this sample.
	 */
	bool applies (const vector<Neighborhood*>& nbr) const;

	/**
	 * Returns the number of minor Rectangle2s.
	 */
	int getMinorRectNum () const {return this->minorRectangle2.size();}

	/**
	 * returns the number of coordinates in the major longinstance (whose label is dominant)
	 */
	int getMajorCooNum () const {return this->majorLongInstance.getOccuranceNum();}


	/** Returns the minor Rectangle2 whose index is given.*/
	Rectangle2 getMinorRect (int index) const {return Rectangle2(this->minorRectangle2[index]);}

	LongInstance getMajorLongInstance () const {return this->majorLongInstance;}

	/** Prints the content of the object to the screen. */
	void print(void) const;

	/** Prints the detailed content of the object to the screen. */
	void printDetail(void) const;

	friend ostream& operator<< (ostream& stream, const Ruletangle2& rt);

	/** 
	 * Returns the amount of information for all the coordinates and rectangles stored in the object.
	 * it adds 2 per coo and 4 per rectangle.
	 */
	int getNetInfoSizeInBits(void) const;

	/** Returns true if the given coordinate is geometrically inside a minor rectangle2. */
	bool hasCooAsMinor (const Coordinate& coo) const;

	/// I have only one constructor to build an object from conflicting LIs but I need to try different 
	/// methods. I write as many as "constructFromConflictingLIs_x() functions and call them in that
	/// constructor.

	/** The first constructor, the one who uses the divideMinErrors() to break the rectangle2 of LI2
	 * it divides the original rectangle into two new ones who have the minimum errors (error: number of
	 * majorLI coos inside a minor rectngle) and repeats this untill all the rectangles are error free.
	 * It does an exhaustive search for the best two rectangles, leading to very heavy computing time.
	 */
	void constructFromConflictingLIs_topdown(const LongInstance& LI1, const LongInstance& LI2, int type = 1);

	/** This function starts from the first coo in the minorLI, creates a rectangle for that. For each
	 * next coo in minorLI, it adds it to the existing rectangle that needs a minimum expansion for
	 * swallowing this coo. It creates a new rectangle for the coo that cannot be swallowed by any existing rectangle.
	 * NOTE: The order matters here but I conider only a random order, since it will have an exponential 
	 * time to solve it if I consider all the orders.
	 */
	void constructFromConflictingLIs_bottomup(const LongInstance& LI1, const LongInstance& LI2, int type = 1);

	/**
	 * This one uses a GA to find the best set of minor rectangles.
	 */
	void constructFromConflictingLIs_evolution(const LongInstance& LI1, const LongInstance& LI2, int type = 1);

	/**
	 * A helper function. Based on the type in the constructor(LI1,LI2,type), it tells which of 
	 * LI1 and LI2 should be the majorLI and which one should be minorLI.
	 */
	void detectMajorAndMinorMembers(	const LongInstance& l1, const LongInstance& l2, LongInstance& majorLI, 
										LongInstance& minorLI, int& majorSize, int& minorSize, int type = 1);


};


